package 算法练习;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/** 

* @author ：soulstones
* @version ：2019年8月16日 上午11:03:47 
* @Description：
* 给出矩阵 matrix 和目标值 target，返回元素总和等于目标值的非空子矩阵的数量。

子矩阵 x1, y1, x2, y2 是满足 x1 <= x <= x2 且 y1 <= y <= y2 的所有单元 matrix[x][y] 的集合。

如果 (x1, y1, x2, y2) 和 (x1', y1', x2', y2') 两个子矩阵中部分坐标不同（如：x1 != x1'），那么这两个子矩阵也不同。

 
输入：matrix = [[1,-1],[-1,1]], target = 0
输出：5
解释：两个 1x2 子矩阵，加上两个 2x1 子矩阵，再加上一个 2x2 子矩阵。

输入：matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
输出：4
解释：四个只含 0 的 1x1 子矩阵。
* 

*/
public class 元素和为目标值的子矩阵数量 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int m = scanner.nextInt();
		int n = scanner.nextInt();
		int target=scanner.nextInt();
		int [] []array =new int [m][n];                  
		for (int i = 0; i < array.length; i++) {                                 //二维数组
			for (int j = 0; j < array[0].length; j++) {
				array[i][j]=scanner.nextInt();                   
			}
		}
		System.out.println(numSubmatrixSumTarget(array, target));
	}
	
private static int numSubmatrixSumTarget(int[][]matrix , int target) {
		int count=0;
		int xlen = matrix.length;
		int ylen = matrix[0].length;
		for(int i=0;i<xlen;i++){     
            for(int j=0;j<ylen;j++){
                if(i==0&&j==0){                    // (0,0)坐标轴
                }else if(i==0){                                                          
                    matrix[0][j] = matrix[0][j-1] + matrix[0][j];                     //x=0即第一横行的相邻左右两个
                }else if(j==0){
                    matrix[i][0] = matrix[i-1][0] + matrix[i][0];                     //j=0即第一个竖行中相邻的上下两个
                }else{                                                                                   //自己+左相邻+上相邻-左上角
                    matrix[i][j] = matrix[i][j] +matrix[i-1][j] + matrix[i][j-1]  - matrix[i-1][j-1];   
                }
            }
        }
		
		
		Map<Integer, Integer> map=new HashMap<>();
		int cha=0;
		Integer t=0;
		Integer s=0;
		for(int step=0; step <ylen;step++) {
			//这里的step指的是，每次遍历(ylen==step+1)的所有的子矩形;第一次遍历ylen=1的所有的子矩形，第二次遍历ylen=2的所有的子矩形,... 
            for(int j=step;j<ylen;j++){
                map.clear();
                map.put(0,1);
                for(int i=0;i<xlen;i++){
                    if(step == 0){
                        cha = matrix[i][j];
                    }else{
                        cha = matrix[i][j] - matrix[i][j-step];
                    }
                    t = map.get(cha);
                    s = map.get(cha-target);
                    if(t!=null){
                       map.put(cha,++t);
                    }else{
                       map.put(cha,1); 
                    }
                    if(s!=null){
                        count += s;
                    }
                }
            }
        }
		return count;
	}
}
